package com.zml.util;

import com.alibaba.fastjson.JSON;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.SimpleBookmark;
import com.spire.pdf.FileFormat;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.bookmarks.PdfBookmark;
import com.spire.pdf.bookmarks.PdfBookmarkCollection;
import com.spire.pdf.general.PdfDestination;
import com.spire.pdf.graphics.PdfMargins;
import com.spire.pdf.graphics.PdfTemplate;
import com.spire.pdf.widget.PdfPageCollection;
import com.zml.pdf.entity.Pdfs;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.RandomStringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.awt.*;
import java.awt.geom.Dimension2D;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Description Description
 * @Author ye.ming
 * @Date Created in 19/12/2
 */
public class PdfUtil {

    private static final int pageSize = 10;
    private static Logger log = LoggerFactory.getLogger(PdfUtil.class);

    @Deprecated
    public static boolean splitPdf(String srcPath, String desPath, int from, int to) {
        PdfDocument pdfDocument = new PdfDocument();
        return false;
    }


    /**
     * 获取Path参数的文件名（最后一级）
     *
     * @param path
     * @return
     */
    public static String getOnlyName(Path path) {
        String fileNameStr = path.getFileName().toString();
        if (fileNameStr.lastIndexOf(".") < 0) {
            return fileNameStr;
        }
        return fileNameStr.substring(0, fileNameStr.lastIndexOf("."));
    }

    /**
     * 获取字符串参数的文件名（最后一级）
     *
     * @param path
     * @return
     */
    public static String getOnlyName(String path) {
        return getOnlyName(Paths.get(path));
    }

    /**
     * 获取Path参数的后缀
     *
     * @param path
     * @return
     */
    public static String getSuffix(Path path) {
        String fileName = path.getFileName().toString();
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    public static String getSuffix(String path) {
        return getSuffix(Paths.get(path));
    }

    /**
     * 删除系统文件或者文件夹
     *
     * @param path
     * @return
     */
    public static boolean deleteFile(Path path) {
        if (path.toString() == null) {
            return true;
        }
        File file = path.toFile();
        if (!file.exists()) {
            return true;
        }
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            if (files == null || files.length == 0) {
                file.delete();
                return true;
            }
            Arrays.asList(files).forEach(f -> {
                if (f.isFile()) {
                    f.delete();
                } else {
                    deleteFile(f.toPath());
                }
            });
            file.delete();
        } else {
            file.delete();
        }
        return true;
    }

    public static boolean deleteFile(String path) {
        return deleteFile(Paths.get(path));
    }


    @Deprecated
    public static boolean splitFile(String srcPathStr, String desPathStr, int from, int to, String encrypt) {

        Path parent = Paths.get(desPathStr).getParent();
//        PdfUtil.deleteFile(parent);


        int splitNum;
        int totalNums;

        PdfDocument doc = new PdfDocument();
        PdfDocument desDoc = new PdfDocument();
        doc.loadFromFile(srcPathStr);
        int numOfPages = doc.getPages().getCount();

        to = to < numOfPages ? to : numOfPages;
        for (int i = from; i < to; i++) {
            PdfPageBase page = doc.getPages().get(i);
            Dimension2D size = page.getSize();
            PdfTemplate template = page.createTemplate();

            PdfPageBase add = desDoc.getPages().add(size, new PdfMargins(0));
            add.getCanvas().drawTemplate(template, new Point(0, 0));
        }

        System.out.println("正在加密的文件分片：" + desPathStr);
        EncryptPDF.EncryptPdf(desDoc, encrypt);

        desDoc.saveToFile(desPathStr, FileFormat.PDF);
        desDoc.dispose();
        doc.dispose();
        return true;
    }


    /**
     * @param filePath 文件的绝对路径
     * @param password 文件的加密密钥
     * @throws IOException
     */
    @Deprecated
    public static int partitionPdfFilePool(String filePath, String password) throws IOException {
        String filePathStr = filePath;
        Path path = Paths.get(filePathStr);
        PdfDocument pdfDocument = new PdfDocument(filePathStr);
        String onlyName = PdfUtil.getOnlyName(path);
        Path parentPath = Paths.get(path.getParent().toString(), onlyName);

        if (parentPath.toFile().exists()) {
            PdfUtil.deleteFile(parentPath);
        }


        int count = pdfDocument.getPages().getCount();
        int totalPartNums = count % 10 != 0 ? count / 10 + 1 : count / 10;
        String parentPathStr = parentPath.toString();

        ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        List<String> desPathList = new ArrayList<>();
        for (int i = 0; i < totalPartNums; i++) {
            desPathList.add(Paths.get(parentPathStr, i + "_" + path.getFileName()).toString());
        }
        pdfDocument.close();

//        desPathList.forEach(System.out::println);

        desPathList.forEach(x -> {
            int index = desPathList.indexOf(x);
            String src = filePathStr;
            String des = x;
            String passwd = password;
            pool.execute(() -> {
                splitFile(src, des, index * 10, (index + 1) * 10, passwd);
            });
        });

        pool.shutdown();
        return totalPartNums;

    }

    /**
     * @param filePath 文件的绝对路径
     * @param password 文件的加密密钥
     * @throws IOException
     */
    @Deprecated
    public static int partitionPdfFile(String filePath, String password) {
        String filePathStr = filePath;
        Path path = Paths.get(filePathStr);
        PdfDocument pdfDocument = new PdfDocument(filePathStr);
        String onlyName = PdfUtil.getOnlyName(path);
        Path parentPath = Paths.get(path.getParent().toString(), onlyName);

        if (parentPath.toFile().exists()) {
            PdfUtil.deleteFile(parentPath);
        }


        int count = pdfDocument.getPages().getCount();
        int totalPartNums = count % 10 != 0 ? count / 10 + 1 : count / 10;
        String parentPathStr = parentPath.toString();

        List<String> desPathList = new ArrayList<>();
        for (int i = 0; i < totalPartNums; i++) {
            desPathList.add(Paths.get(parentPathStr, i + "_" + path.getFileName()).toString());
        }
        pdfDocument.close();


//        desPathList.forEach(System.out::println);

        desPathList.forEach(x -> {
            final int index = desPathList.indexOf(x);
            final String src = filePathStr;
            final String des = x;
            final String passwd = password;
            splitFile(src, des, index * 10, (index + 1) * 10, passwd);
        });

        return totalPartNums;

    }

    /**
     * 获取路径文件的书签 (采用spire.pdf for java 框架)
     * 解析发现书签存在乱码，猜测原因是部分目录存在特殊字符导致
     *
     * @param filePathStr
     * @return
     */
    public static List<BookMarkEntity> getPdfBookMarkA(String filePathStr) {

        List<BookMarkEntity> bookList = new ArrayList<>();

        PdfDocument doc = new PdfDocument();
        doc.loadFromFile(filePathStr);
        PdfBookmarkCollection bookmarks = doc.getBookmarks();
        if (bookmarks == null) {
            return bookList;
        }

        PdfPageCollection pages = doc.getPages();
        int count = bookmarks.getCount();

        for (int i = 0; i < count; i++) {
            bookList.add(convertBookMark(pages, bookmarks.get(i)));
        }

        doc.dispose();
        return bookList;
    }

    /**
     * 将书签转换为自定义的书签类
     *
     * @param pageCollection
     * @param bookmark
     * @return
     */
    public static BookMarkEntity convertBookMark(PdfPageCollection pageCollection, PdfBookmark bookmark) {
        BookMarkEntity entity = new BookMarkEntity();
        List<BookMarkEntity> subBookMark = new ArrayList<>();

        if (bookmark == null) {
            entity.setSubBookMark(subBookMark);
            return entity;
        }

        entity.setTitle(bookmark.getTitle());
        PdfDestination destination = bookmark.getDestination();
        if (pageCollection != null && destination != null) {
            entity.setDesPageNum(pageCollection.indexOf(destination.getPage()));
        } else {
            entity.setDesPageNum(-1);
        }

        int count = bookmark.getCount();
        if (count != 0) {
            for (int i = 0; i < count; i++) {
                subBookMark.add(convertBookMark(pageCollection, bookmark.get(i)));
            }
        }
        entity.setSubBookMark(subBookMark);
        return entity;

    }

    /**
     * @Description:生成一个pdfs实体类
     * @AuthorOrModify: ye.ming
     * @Date: 19/12/6
     */
    public static Pdfs getPdfs() {
        Pdfs p = new Pdfs();
        String uuid = UuidUtil.get32UUID();
        File resFile = FileUtils.getFile("PdfFiles");
        if (!resFile.exists()) {
            resFile.mkdirs();
        }
        Path dirPath = Paths.get(resFile.getAbsolutePath(), uuid);
        String dirPathStr = dirPath.toString();
        p.setId(uuid);
        p.setPath(dirPathStr);
        p.setPdfUrl(Paths.get(dirPathStr + ".pdf").toString());
        p.setJsonUrl(Paths.get(dirPathStr, uuid + ".json").toString());
        p.setTime(DateUtil.getTime());
        p.setOpenKey(RandomStringUtils.randomAlphanumeric(16));
        return p;
    }

    /**
     * 验证一个文件是否是pdf文件
     *
     * @param fileName
     * @return
     */
    public static boolean valid(String fileName) {
        log.info(fileName);
        if (!fileName.toLowerCase().endsWith(".pdf")) {
            log.info("上传了一个非PDf文件！");
            return false;
        }
        return true;
    }

    /**
     * 获取pdf书签 (采用 itext for core 5.x 框架) 暂时未发现乱码
     *
     * @param filename
     * @return
     */
    public static List<BookMarkEntity> getPdfBookMarkB(String filename) {
        PdfReader reader = null;
        List<BookMarkEntity> list = new ArrayList<>();
        try {
            reader = new PdfReader(filename);
        } catch (IOException e) {
            e.printStackTrace();
            return list;
        }
        List<HashMap<String, Object>> bookmarks = SimpleBookmark.getBookmark(reader);
        if (bookmarks != null) {
            for (int i = 0; i < bookmarks.size(); i++) {
                list.add(convertBmMap(bookmarks.get(i)));
            }
        }

        if (reader != null) {
            reader.close();
        }
        return list;
    }

    public static BookMarkEntity convertBmMap(HashMap<String, Object> bm) {
        BookMarkEntity entity = new BookMarkEntity();
        Object titleObj = bm.get("Title");
        if (titleObj != null) {
            entity.setTitle(bm.get("Title").toString().replaceFirst("\r", " "));
        }


        Object pageObj = bm.get("Page");
       if (pageObj!=null){
    	   entity.setDesPageNum(Integer.parseInt(bm.get("Page").toString().split(" ")[0]));
       }
       else
       {
    	   entity.setDesPageNum(1);
       }
        ArrayList<BookMarkEntity> list = new ArrayList<>();
        List<HashMap<String, Object>> kids = (List<HashMap<String, Object>>) bm.get("Kids");
        if (kids != null) {
            for (int i = 0; i < kids.size(); i++) {
                list.add(convertBmMap(kids.get(i)));
            }
        }
        entity.setSubBookMark(list);
        return entity;
    }

    public static List<BookMarkEntity> mergeBookMark(List<BookMarkEntity> list1, List<BookMarkEntity> list2) {

        if (list1 == null || list1.size() < 1) {
            return list2;
        } else if (list2 == null || list2.size() < 1) {
            return list1;
        } else {
            int s1 = list1.size();
            int s2 = list2.size();
            if (s1 > s2) {
                return list1;
            } else if (s1 < s2) {
                return list2;
            } else {
                for (int i = 0; i < s1; i++) {
                    BookMarkEntity b1 = list1.get(i);
                    BookMarkEntity b2 = list2.get(i);
                    b1.setTitle(b2.getTitle());
                    b1.setSubBookMark(mergeBookMark(b1.getSubBookMark(),b2.getSubBookMark()));
                    list1.set(i, b1);
                }
            }

        }
        return list1;
    }

    public static List<BookMarkEntity> getPdfBookMark(String filePathStr) {

        return mergeBookMark(getPdfBookMarkA(filePathStr), getPdfBookMarkB(filePathStr));

    }



    public static void main(String[] args) {
        String src = "C:\\Users\\admin\\Desktop\\32678.pdf";
        List<BookMarkEntity> mark = getPdfBookMark(src);
        System.out.println(JSON.toJSON(mark));

    }


}
